﻿// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SnapObjects.Data
{
    abstract class ProcedureColumnSchemaProvider : ColumnSchemaProvider
    {
        public ProcedureColumnSchemaProvider(DataContext dataContext) : base(dataContext)
        {
        }

        public virtual IReadOnlyList<IReadOnlyList<DbColumnInfo>> GetColumnSchema(
            string procedure, IEnumerable<IAdoDbParameter> parameters)
        {
            _dataContext.CurrentConnection.Open();

            IAdoDbDataVisitor dataVisiter = null;

            try
            {
                var adoDbProvider = _dataContext.AdoDbProviderFactory.GetAdoDbProvider();

                parameters = parameters ?? new List<IAdoDbParameter>();

                var adoParams = this.CloneAdoDbParameter(parameters);

                dataVisiter = adoDbProvider.ExecuteSqlProcedure(procedure, adoParams, this.GetCommandBehavior());

                var reader = dataVisiter.ReadData();

                var columnSchemas = this.GetDbColumnInfo(reader);

                return columnSchemas;
            }
            finally
            {
                dataVisiter?.Dispose();
                _dataContext.CurrentConnection.Close();
            }
        }

        public async virtual Task<IReadOnlyList<IReadOnlyList<DbColumnInfo>>> GetColumnSchemaAsync(
            string procedure, IEnumerable<IAdoDbParameter> parameters, CancellationToken cancellationToken)
        {
            await _dataContext.CurrentConnection.OpenAsync(cancellationToken);

            IAdoDbDataVisitor dataVisitor = null;

            try
            {
                var adoDbProvider = _dataContext.AdoDbProviderFactory.GetAdoDbProvider();

                parameters = parameters ?? new List<IAdoDbParameter>();

                var adoParams = this.CloneAdoDbParameter(parameters);

                dataVisitor = await adoDbProvider.ExecuteSqlProcedureAsync(
                    procedure, adoParams, this.GetCommandBehavior(), cancellationToken);

                var reader = dataVisitor.ReadData();

                var columnSchemas = this.GetDbColumnInfo(reader);

                return columnSchemas;
            }
            finally
            {
                if (dataVisitor != null)
                {
                    await dataVisitor.DisposeAsync();
                }

                await _dataContext.CurrentConnection.CloseAsync();
            }
        }

        protected override CommandBehavior GetCommandBehavior()
        {
            return CommandBehavior.Default;
        }

        protected override bool AllowDbNull(DataRow row, IDataReader reader)
        {
            return true;
        }

        protected override bool IsAliased(DataRow row, IDataReader reader)
        {
            return false;
        }

        protected override bool IsTimestamp(DataRow row, IDataReader reader)
        {
            return false;
        }

        protected override bool IsIdentity(DataRow row, IDataReader reader)
        {
            return false;
        }

        protected override bool IsReadOnly(DataRow row, IDataReader reader)
        {
            return false;
        }

        protected override bool IsExpression(DataRow row, IDataReader reader)
        {
            return false;
        }

        protected override bool IsHidden(DataRow row, IDataReader reader)
        {
            return false;
        }

        protected override bool IsNotInWhere(DataRow row, IDataReader reader)
        {
            return true;
        }
    }
}
